﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_OCF_Parser.h".
//-------------------------------------------------------------------

#ifndef _UXS_CONFIGURATION_FILE_PARSER_H
#define _UXS_CONFIGURATION_FILE_PARSER_H

#pragma once

#include "ConfigTypes.h"
#include "Parser.h"

namespace UX_STL
{
namespace UXParser
{

	class CConfig;

	struct TConfigObjInfo
	{
		CMetaSetIterator  *	pIter;
		const string		sName;
		bool				bUsed;
		///
		TConfigObjInfo(): pIter(null), bUsed(true) {}
		TConfigObjInfo(CMetaSetIterator *iter, uni_c_string name): pIter(iter), sName(name), bUsed(false) {}
	};
	

	struct TConfigObjInfoConstructor
	{
		static void CreateDefault(TConfigObjInfo &e)				{}
		static void Create(TConfigObjInfo &e)						{}
		static void Destroy(TConfigObjInfo &e)						{ if ( e.pIter != null ) e.pIter->Free(); }
		static void Copy(TConfigObjInfo &from, TConfigObjInfo &to)	{}
	};


	typedef tree< TConfigObjInfo, TConfigObjInfoConstructor >		static_obj_tree_t;
	typedef static_obj_tree_t::iterator								static_obj_node_t;
	typedef static_obj_tree_t::const_iterator						save_obj_node_t;


	class UX_EXPORT IConfigProcessStrategy
	{
	public:
		virtual bool Create(static_obj_node_t &pObjects, const CCfgBaseElement *pCfgObj, CMetaSetIterator *&pIter, bool &bNeedDelete) = 0;
	};



	//
	// Config Container
	//

	class UX_EXPORT CConfigContainer
	{
		friend class UX_STL::UXParser::CConfig;
		friend struct TConfigObjTreeUpdater;

	private:
		string							_sFileName;
		config_tree_t					_sObjectsTree;
		Ptr< static_obj_node_t >		_pObjects;
		Ptr< IConfigProcessStrategy >	_pStrategy;

	private:
		void _CheckObj(TConfigObjInfo &sInfo) const;
		bool _RecursiveProcessVarArray(config_const_node_t pNode, CMetaVarArrayIterator *pIter);
		bool _RecursiveProcessArray(config_const_node_t pNode, CMetaArrayIterator *pIter);
		bool _ProcessStructElem(config_const_node_t pNode, CMetaStructIterator *pIter);
		bool _ProcessInitList(config_const_node_t pNode, CMetaSetIterator *pIter);
		bool _RecursiveSet(config_const_node_t pNode, CMetaSetIterator *pIter);

	public:
		CConfigContainer(const string &sFileName);
		~CConfigContainer();

		bool ClearTree();
		void Release();

		bool Process(IConfigProcessStrategy *pStrategy = null);
		bool Process(static_obj_node_t pObjects, IConfigProcessStrategy *pStrategy = null);

		config_const_node_t	GetObjTree()	const	{ return _sObjectsTree.First(); }
		const string	&	GetFileName()	const	{ return _sFileName; }
	};

	
	typedef AutoPtr< CConfigContainer >	CConfigContainerPtr;



	//
	// Config System
	//
	
	class UX_EXPORT CConfig
	{
	private:
		//array< CConfigContainer *>	_aContainers;
		array< IParser *>			_aParsers;
		string_array_t				_aDefDirectories;
		IParser					*	_pOCFParser;
		string						_sParsedFilesDir;
		bool						_bSaveParsed;

	protected:
		void  _Clear ();

	public:
		CConfig ();
		~CConfig ();

		bool Parse (IParser *pParser, RFilePtr pFile, CConfigContainer *&pObj, uint uFileSize = 0, const string_array_t *pDirectory = null);
		bool Parse (RFilePtr pFile, CConfigContainer *&pObj, uint uFileSize = 0, const string_array_t *pDirectory = null);
		bool Parse (uni_c_string pFileName, CConfigContainer *&pObj, const string_array_t *pDirectory = null);

		bool Save (WFilePtr pFile, save_obj_node_t pObjects);
		bool Save (uni_c_string pFileName, save_obj_node_t pObjects);

		bool AddDirectory (uni_c_string sDirectory);
		bool RemoveDirectory (uni_c_string sDirectory);
		void ClearDerectories ();

		bool GetParser (uni_c_string sFileExt, IParser *&pParser);
		bool RegisterParser (IParser *pParser, bool bHighPriority = false);
		bool UnregisterParser (IParser *pParser);

		//bool RemoveContainer (CConfigContainer *pCC);

		// debug
		void SaveParsedFiles (bool bSave);
		bool SetParsedFilesDirectory (uni_c_string pDir);
	};
	
//-------------------------------------------------------------------

}	// UXParser
}	// UX_STL

#endif	// _UXS_CONFIGURATION_FILE_PARSER_H